#include "teststdafx.h"
#include "stdafx.h"

#pragma warning(disable:4996)
#include <gtest/gtest.h>

#include "Business/Market.h"

class MarketTest : public testing::Test
{
protected:

	virtual void SetUp()
	{
		CreateMarket();
	}

	virtual void TearDown()
	{

	}
	Market& CreateMarket()
	{
		Variety variety("rb1010",1,10);
		Margins margins;
		margins.Add(Margin("test1",0.1));
		margins.Add(Margin("test2",0.2));
		variety.SetMargins(margins);
		Charge openExchageCharge("open exchange charge",Charge::PERCENT, 0.10);
		Charge openCompanyCharge("open company charge",Charge::PER_QUANTITY, 5);
		Charge offsetExchangeCharge("offset exchange charge",Charge::PER_QUANTITY, 10);
		Charge offsetCompanyCharge("offset company charge",Charge::PERCENT, 0.10);

		Charges openCharges;
		openCharges.push_back(openExchageCharge);
		openCharges.push_back(openCompanyCharge);
		Charges offsetCharges;
		offsetCharges.push_back(offsetExchangeCharge);
		offsetCharges.push_back(offsetCompanyCharge);

		variety.SetOperationCharges(Operation::OPEN, openCharges);
		variety.SetOperationCharges(Operation::OFFSET,offsetCharges);
		double lastPrice = 3000.00;
		Prices buyPrices;
		buyPrices[0] = Price(3010,7);
		Prices sellPrices;
		sellPrices[0] = Price(2990,6);
		double upperLimit = 4000.00;
		double lowerLimit = 2000.00;
		double preSettlementPrice  = 3100.00;
		static Market s_market(0,variety,lastPrice,0,buyPrices,sellPrices,upperLimit,lowerLimit,preSettlementPrice); 
		return s_market;
	}
	
	void foo();
};

TEST_F(MarketTest, MarginsTest)
//void foo()
{
	Margins margins;
	margins.Add(Margin("test1",0.1));
	EXPECT_DOUBLE_EQ(0.1,margins.GetTotalMargin());
	margins.Add(Margin("test2",0.2));
	EXPECT_DOUBLE_EQ(0.3,margins.GetTotalMargin());

	Variety variety("cu1005",1,10);
	variety.SetMargins(margins);
	EXPECT_DOUBLE_EQ(0.3,variety.GetTotalMargin());
}

TEST_F(MarketTest,ChargeTest)
//void foo()
{
	Charge openExchageCharge("open exchange charge",Charge::PERCENT, 0.05);
	Charge openCompanyCharge("open company charge",Charge::PER_QUANTITY, 5);
	Charge offsetExchangeCharge("offset exchange charge",Charge::PER_QUANTITY, 10);
	Charge offsetCompanyCharge("offset company charge",Charge::PERCENT, 0.05);

	EXPECT_DOUBLE_EQ(100,openExchageCharge.CalculateCharge(1000,2));
	EXPECT_DOUBLE_EQ(10,openCompanyCharge.CalculateCharge(1000,2));
	EXPECT_DOUBLE_EQ(50,offsetExchangeCharge.CalculateCharge(1000,5));
	EXPECT_DOUBLE_EQ(250,offsetCompanyCharge.CalculateCharge(1000,5));

	Charges openCharges;
	openCharges.push_back(openExchageCharge);
	openCharges.push_back(openCompanyCharge);
	Charges offsetCharges;
	offsetCharges.push_back(offsetExchangeCharge);
	offsetCharges.push_back(offsetCompanyCharge);

	Variety variety("cu1005",1,10);
	variety.SetOperationCharges(Operation::OPEN,openCharges);
	variety.SetOperationCharges(Operation::OFFSET_TODAY,offsetCharges);
	EXPECT_DOUBLE_EQ(1100,variety.CalculateCharge(1000,2,Operation::OPEN));
	EXPECT_DOUBLE_EQ(3000,variety.CalculateCharge(1000,5,Operation::OFFSET_TODAY));

}

TEST_F(MarketTest,CalculateChargeTest)
// void foo()
{
	Market const& market = CreateMarket();
	double price = 1000.00;
	int quantity = 10;

	double expectedCharge = (price * 0.1 + 5) * quantity * 10;
	EXPECT_DOUBLE_EQ(expectedCharge, market.CalculateCharge(price,quantity,Operation::OPEN));

	expectedCharge = 0.00;
	EXPECT_DOUBLE_EQ(expectedCharge, market.CalculateCharge(price,quantity,Operation::OFFSET_TODAY));

	expectedCharge = (price * 0.1 + 10) * quantity * 10;
	EXPECT_DOUBLE_EQ(expectedCharge, market.CalculateCharge(price,quantity,Operation::OFFSET));
}

TEST_F(MarketTest,CalculateMarginTest)
//void foo()
{
	Market const& market = CreateMarket();
	int quantity = 10;

	double expectedMargin = market.GetPreSettlementPrice() * market.GetMarginRate() * quantity * 10;
	EXPECT_DOUBLE_EQ(expectedMargin, market.CalculateMargin(quantity,Operation::OPEN));

	expectedMargin = 0.00;
	EXPECT_DOUBLE_EQ(expectedMargin, market.CalculateMargin(quantity,Operation::OFFSET_TODAY));

	EXPECT_DOUBLE_EQ(expectedMargin, market.CalculateMargin(quantity,Operation::OFFSET));
}

TEST_F(MarketTest,CalculateFreezeAmountTest)
// void foo()
{
	Market const& market = CreateMarket();
	double price = 1000.00;
	int quantity = 10;

	double expectedCharge = (price * 0.1 + 5) * quantity;
	double expectedMargin = market.GetPreSettlementPrice() * market.GetMarginRate() * quantity;
	double expectedAmount = (expectedCharge + expectedMargin) * 10;
	EXPECT_DOUBLE_EQ(expectedAmount, market.CalculateFreezeAmount(price,quantity,Operation::OPEN));

	expectedCharge = 0.00;
	expectedMargin = 0.00;
	expectedAmount = (expectedCharge + expectedMargin) * 10;
	EXPECT_DOUBLE_EQ(expectedAmount, market.CalculateFreezeAmount(price,quantity,Operation::OFFSET_TODAY));

	expectedCharge = (price * 0.1 + 10) * quantity;
	expectedAmount = 0.00;
	expectedAmount = (expectedCharge + expectedMargin) * 10;
	EXPECT_DOUBLE_EQ(expectedAmount, market.CalculateFreezeAmount(price,quantity,Operation::OFFSET));
}
static std::ostream& operator<<(std::ostream& os, Prices const& prices)
{
	return os;
}

TEST_F(MarketTest, UpdatePriceTest) /*
void MarketTest::foo() /**/
{
	Variety variety("UNDEFINED",-1,-1);
	double lastPrice = 3500.00;
	Prices buyPrices;
	buyPrices[0] = Price(3100,10);
	Prices sellPrices;
	sellPrices[0] = Price(2180,5);
	double upperLimit = 4100.00;
	double lowerLimit = 2100.00;
	double preSettlementPrice  = 3120.00;
	Market market(0,variety,lastPrice,0,buyPrices,sellPrices,upperLimit,lowerLimit,preSettlementPrice); 
	Market& existMarket = CreateMarket();
	existMarket.UpdatePrice(market);

	EXPECT_DOUBLE_EQ(market.GetLastPrice(),existMarket.GetLastPrice());
	EXPECT_EQ(market.GetBuyPrices(),existMarket.GetBuyPrices());
	EXPECT_EQ(market.GetSellPrices(),existMarket.GetSellPrices());
	EXPECT_DOUBLE_EQ(market.GetPreSettlementPrice(),existMarket.GetPreSettlementPrice());
	EXPECT_DOUBLE_EQ(market.GetUpperLimit(),existMarket.GetUpperLimit());
	EXPECT_DOUBLE_EQ(market.GetLowerLimit(),existMarket.GetLowerLimit());

}

TEST_F(MarketTest, IsCloseLimitTest) /*
void MarketTest::foo() /**/
{
	Variety variety("UNDEFINED",-1,-1);
	// update market 0
	{
		double lastPrice = 3980.00;
		Prices buyPrices;
		buyPrices[0] = Price(3000,10);
		Prices sellPrices;
		sellPrices[0] = Price(2980,5);
		double upperLimit = 4000.00;
		double lowerLimit = 2000.00;
		double preSettlementPrice  = 3100.00;
		Market market(0,variety,lastPrice,0,buyPrices,sellPrices,upperLimit,lowerLimit,preSettlementPrice); 
		EXPECT_EQ(true, market.IsCloseLimit());
	}
	{
		double lastPrice = 3970.00;
		Prices buyPrices;
		buyPrices[0] = Price(3000,10);
		Prices sellPrices;
		sellPrices[0] = Price(2980,5);
		double upperLimit = 4000.00;
		double lowerLimit = 2000.00;
		double preSettlementPrice  = 3100.00;
		Market market(0,variety,lastPrice,0,buyPrices,sellPrices,upperLimit,lowerLimit,preSettlementPrice); 
		EXPECT_EQ(false, market.IsCloseLimit());
	}
	{
		double lastPrice = 2010.00;
		Prices buyPrices;
		buyPrices[0] = Price(3000,10);
		Prices sellPrices;
		sellPrices[0] = Price(2980,5);
		double upperLimit = 4000.00;
		double lowerLimit = 2000.00;
		double preSettlementPrice  = 3100.00;
		Market market(0,variety,lastPrice,0,buyPrices,sellPrices,upperLimit,lowerLimit,preSettlementPrice); 

		EXPECT_EQ(true, market.IsCloseLimit());
	}
	{
		double lastPrice = 2020.00;
		Prices buyPrices;
		buyPrices[0] = Price(3000,10);
		Prices sellPrices;
		sellPrices[0] = Price(2980,5);
		double upperLimit = 4000.00;
		double lowerLimit = 2000.00;
		double preSettlementPrice  = 3100.00;
		Market market(0,variety,lastPrice,0,buyPrices,sellPrices,upperLimit,lowerLimit,preSettlementPrice); 

		EXPECT_EQ(false, market.IsCloseLimit());
	}
}